import {cloneDeep} from 'lodash-unified'

export function buildTree(array, config) {
  validList(array)
  array = cloneDeep(array)
  const rootId = config?.rootId || null
  const idKey = config?.idKey || 'uniqueProp'
  const pIdKey = config?.pIdKey || 'parentUniqueProp'
  const sortKey = config?.sortKey || 'sortNumber'
  const sortDirection = config?.sortDirection || 'asc' // 'asc' 'desc'
  // 是否自动生成顺序号 如果传值为true， 则以传入的数组的顺序生成序号， 如果传入false，则以字段 sortKey 对应的值为顺序
  const autoGenSortNumber = !!config?.autoGenSortNumber

  function sortFn(a, b) {
    return sortDirection === 'asc'
      ? (a[sortKey] || 0) - (b[sortKey] || 0)
      : (b[sortKey] || 0) - (a[sortKey] || 0)
  }

  let result = []
  const itemMap = {}
  for (const item of array) {
    const id = item[idKey]
    const pid = item[pIdKey]
    if (!itemMap[id]) {
      itemMap[id] = {
        children: [],
      }
    }
    itemMap[id] = {
      ...item,
      children: itemMap[id].children,
    }
    const treeItem = itemMap[id]
    if (pid === rootId) {
      result.push({
        ...treeItem,
        ...(autoGenSortNumber ? {[sortKey]: result.length + 1} : {}),
      })
      result = result.sort(sortFn)
    } else {
      if (!itemMap[pid]) {
        itemMap[pid] = {
          children: [],
        }
      }
      itemMap[pid].children.push({
        ...treeItem,
        ...(autoGenSortNumber ? {[sortKey]: itemMap[pid].children.length + 1} : {}),
      })
      itemMap[pid].children = itemMap[pid].children.sort(sortFn)
    }
  }
  return result
}

function validList(list) {
  const hasChildren = list.some((item) => item.children)
  if (hasChildren) {
    throw new Error('将要转化为树的列表不允许存在children属性！')
  }
}

// export function getListByTree(tree) {
//   const list = []
//
//   function getList(treeList) {
//     treeList.forEach((item) => {
//       const { children, ...other } = item
//       list.push(other)
//       if (children?.length) {
//         getList(children)
//       }
//     })
//   }
//
//   getList(cloneDeep(tree))
//   return list
// }

export function getListByTree(tree, withoutChildren = true) {
  const array = []
  const stack = [...tree]
  while (stack.length) {
    const item = stack[0]
    const {children, ...withoutChildrenItem} = item
    array.push(withoutChildren ? withoutChildrenItem : item)
    stack.shift()
    if (item.children && item.children.length) {
      stack.push(...item.children)
    }
  }
  return array
}

export function sortList(list, config) {
  return getListByTree(buildTree(list, config))
}

export function getSortMap(list) {
  return list.map((item) => ({[item.id]: item})).reduce((p, c) => ({...p, ...c}))
}

/**
 * 以1为模板，返回2改变了哪些
 * @param sortMap1
 * @param sortMap2
 */
export function compareSortMap(sortMap1, sortMap2) {
  const result = {}
  Object.keys(sortMap1).forEach((key) => {
    if (sortMap1[key].sortNumber !== sortMap2[key].sortNumber) {
      result[key] = {
        id: sortMap2[key].id,
        sortNumber: sortMap2[key].sortNumber,
      }
    }
  })
  if (Object.keys(result).length) {
    return result
  }
  return null
}

function filterByKeys(schema, list, prop = 'name') {
  const itemMap = new Map(schema.map(item => [item[prop], item]))
  return list.map(code => itemMap.get(code)).filter(Boolean)
}

